/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.worsik.vypocty.topeni.tepelneztraty.model.table;

import cz.worsik.vypocty.topeni.tepelneztraty.model.Mistnost;
import cz.worsik.vypocty.topeni.tepelneztraty.model.Otvor;
import cz.worsik.vypocty.topeni.tepelneztraty.model.Stena;
import cz.worsik.vypocty.topeni.tepelneztraty.model.SvetovaStrana;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.table.DefaultTableModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author 231260
 */
public class OtvoryTableModel extends DefaultTableModel {
	
	private static final Logger log = LoggerFactory.getLogger(OtvoryTableModel.class);
	
	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport( this );
	
	private Mistnost mistnost;
	//private List<Stena> stenyList;
	private List<SloupecTableModel> sloupce = new ArrayList<SloupecTableModel>(Arrays.asList(
		new SloupecTableModel("Otvor","Název otvoru",false,String.class,40,""),
		new SloupecTableModel("Stěna","Název stěny",false,String.class,40,""),
		new SloupecTableModel("Délka","Délka (mm)",true,Integer.class,50,"setDelka"),
		new SloupecTableModel("Výška","Výška (mm)",true,Integer.class,50,"setVyska"),
		new SloupecTableModel("Spáry","Délka spar (mm)",true,Integer.class,50,"setDelkaSpar"),
		new SloupecTableModel("Strana","Světová strana",false,SvetovaStrana.class,60,""),
		new SloupecTableModel("Plocha","<html>Plocha otvoru (m<sup>2</sup>)</html>",false,Double.class,50,""),
		new SloupecTableModel("SPT","<html>Součinitel prostupu tepla (Wm<sup>-2</sup> K<sup>-1</sup> )</html>",true,Double.class,30,"setSoucinitel_k"),
		new SloupecTableModel("TZK","Teplota za konstrukcí",false,Integer.class,30,""),
		new SloupecTableModel("Tepelná ztráta","Tepelná ztráta (W)",false,Double.class,80,""),
		new SloupecTableModel("ILV","<html>Součinitel spárové průvzdušnosti i<sub>L,V</sub> ( &middot; 10<sup>-4</sup> m<sup>3</sup>/ m &middot; s &middot; Pa<sup>0,67</sup> )</html>",true,Double.class,30,"setSoucinitel_i"),
		new SloupecTableModel("Infiltrace","Tepelná ztráta větráním (W)",false,Double.class,80,"")
	));
	
	public OtvoryTableModel(Mistnost mistnost) {
		this.mistnost = mistnost;
		//stenyList = new ArrayList<Stena>();
	}
	
	public void addPropertyChangeListener( PropertyChangeListener listener ) {
		propertyChangeSupport.addPropertyChangeListener( listener );
    }
	
	public int getColumnWidth(int i)
	{
		return sloupce.get(i).getSirka();
	}
	
	public String getColumnPopis(int i)
	{
		return sloupce.get(i).getPopis();
	}
	
	public void addOtvor(int index_steny, boolean je_okno)
	{
		Stena stena = mistnost.getStenyList().get(index_steny);
		Otvor otvor = new Otvor(je_okno);
		
		otvor.setNazev(getRowCount()+1);
		otvor.setDelka(1500);
		otvor.setVyska(1500);
		
		mistnost.getStenyList().get(index_steny).addOtvor(otvor);
		mistnost.getStenyList().get(index_steny).nastavVychoziSoucinitelOtvoru(otvor);
		
		// -1 je nutna kvuli tomu, ze pomoc addOtvor jsme zvetsili pole otvoru a tedy i RowCount
		insertRow(getRowCount()-1, otvor.getRowData(stena));
		
		log.debug("Přidán otvor "+otvor.getNazev()+" do stěny "+stena.getNazev());
		log.debug("Nyní je v místnosti "+getRowCount()+" otvorů");
	}
	
	public void removeOtvor(int row)
	{
		removeRow(row);
		Stena s = getStena(row);
		Otvor o = getOtvor(row);
		
		log.debug("Smazán otvor "+o.getNazev()+" ve stěně "+s.getNazev());
		
		int index_s = mistnost.getStenyList().indexOf(s);
		mistnost.getStenyList().get(index_s).removeOtvor(getIndexOtvoruVeStene(row));
		
		refresh();
		
		log.debug("Nyní je v místnosti "+getRowCount()+" otvorů");
	}

	@Override
	public int getRowCount() {
		int count = 0;
		
		if (mistnost == null || mistnost.getStenyList() == null)
			return count;
		
		for (Stena stena : mistnost.getStenyList())
		{
			count += stena.getOtvoryList().size();
		}
		
		return count;
	}

	@Override
	public int getColumnCount() {
		return sloupce.size();
	}

	@Override
	public String getColumnName(int i) {
		return sloupce.get(i).getNazev();
	}

	@Override
	public Class<?> getColumnClass(int i) {
		return sloupce.get(i).getTrida();
	}

	@Override
	public boolean isCellEditable(int row, int col) {
		//return false;
		
		return sloupce.get(col).getEditovatelny();
	}

	@Override
	public Object getValueAt(int row, int col) {
		return super.getValueAt(row, col);
	}

	@Override
	public void setValueAt(Object o, int row, int col) {

		Object old = getValueAt(row, col);
		
		getOtvor(row).setProperty(
			sloupce.get(col).getSetter(),
			o,
			sloupce.get(col).getTrida()
		);
		removeRow(row);
		Object[] row_data = getOtvor(row).getRowData(getStena(row));
		insertRow(row, row_data);
		
		propertyChangeSupport.firePropertyChange( "otvoryList", old, o );
	}
	
	public Stena getStena(int row)
	{
		if (row < 0)
		{
			log.warn("Snažíme se získat přístup ke stene s otvorem se záponým indexem.");
			return null;
		}
		
		for (int i = 0; i <= mistnost.getStenyList().size(); i++)
		{
			Stena stena = mistnost.getStenyList().get(i);
			if (stena.getOtvoryList().size() > row)
			{
				return stena;
			}
			else
			{
				row -= stena.getOtvoryList().size();
			}
		}
		
		log.warn("Snažíme se získat přístup ke stene s otvorem s příliš velkým indexem.");
		return null;
	}
	
	public Otvor getOtvor(int row)
	{
		if (row < 0)
		{
			log.warn("Snažíme se získat přístup k otvoru se záponým indexem.");
			return null;
		}
		
		for (int i = 0; i <= mistnost.getStenyList().size(); i++)
		{
			Stena stena = mistnost.getStenyList().get(i);
			if (stena.getOtvoryList().size() > row)
			{
				return stena.getOtvoryList().get(row);
			}
			else
			{
				row -= stena.getOtvoryList().size();
			}
		}
		
		log.warn("Snažíme se získat přístup k otvoru s příliš velkým indexem.");
		return null;
	}
	
	public int getIndexOtvoruVeStene(int row)
	{
		if (row < 0)
		{
			log.warn("Snažíme se získat přístup k otvoru se záponým indexem.");
			return -1;
		}
		
		for (int i = 0; i <= mistnost.getStenyList().size(); i++)
		{
			Stena stena = mistnost.getStenyList().get(i);
			if (stena.getOtvoryList().size() > row)
			{
				return row;
			}
			else
			{
				row -= stena.getOtvoryList().size();
			}
		}
		
		log.warn("Snažíme se získat přístup k otvoru s příliš velkým indexem.");
		return -1;
	}
	
	public void removeOtvoryVeStene(int index_steny)
	{
		if (index_steny < 0)
		{
			log.warn("Snažíme se získat přístup ke stene se záponým indexem.");
			return;
		}
		
		int pocatek = 0;
		int konec = 0;
		
		for (int i = 0; i <= index_steny; i++)
		{
			Stena stena = mistnost.getStenyList().get(i);
			if (i < index_steny)
			{
				pocatek += stena.getOtvoryList().size();
				konec = pocatek;
			}
			else
			{
				konec = pocatek + stena.getOtvoryList().size()-1;
				log.debug("Budeme mazat otvory s indexy "+pocatek+" až "+konec);
				return;
				//stena.removeVsechnyOtvory();
			}
		}
		
		log.warn("Snažíme se získat přístup ke stene s příliš velkým indexem.");
		return;
	}
	
	public void refresh()
	{
		for (int row=0; row<getRowCount(); row++)
		{
			getStena(row).nastavVychoziSoucinitelOtvoru(getOtvor(row));
			removeRow(row);
			insertRow(row, getOtvor(row).getRowData(getStena(row)));
		}
		
		propertyChangeSupport.firePropertyChange( "refresh", "nic", "něco" );
	}

	public String[] getPopiskyProToolTip()
	{
		String[] popisky = new String[sloupce.size()];
		for (int i=0; i<sloupce.size(); i++)
		{
			popisky[i] = sloupce.get(i).getPopis();
		}
		return popisky;
	}
	/*
	public void setSumy()
	{
		Double ztrata = 0d;
		Double plocha = 0d;
		
		for (Stena stena : stenyList)
		{
			ztrata += stena.getTepelnaZtrata();
			plocha += stena.getPlochaBezOtvoru();
		}
		
		mistnost.setTepelna_ztrata(ztrata);
		mistnost.setPlocha_sten(plocha);
	}
	
	public Mistnost getMistnost()
	{
		return mistnost;
	}*/
}
